﻿using System;
using System.Collections.Generic;
using System.Text;
using ActiproSoftware.SyntaxEditor;
using ActiproSoftware.SyntaxEditor.ParserGenerator;

namespace WindowsUserControl.Codes
{
    /// <summary>
    /// Represents a <c>Simple</c> recursive descent lexical parser implementation.
    /// </summary>
    internal class SimpleRecursiveDescentLexicalParser : MergableRecursiveDescentLexicalParser
    {

        /////////////////////////////////////////////////////////////////////////////////////////////////////
        // OBJECT
        /////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Initializes a new instance of the <c>SimpleRecursiveDescentLexicalParser</c> class.
        /// </summary>
        /// <param name="language">The <see cref="SimpleSyntaxLanguage"/> to use.</param>
        /// <param name="manager">The <see cref="MergableLexicalParserManager"/> to use for coordinating merged languages.</param>
        public SimpleRecursiveDescentLexicalParser(SimpleSyntaxLanguage language, MergableLexicalParserManager manager) : base(language, manager) { }

        /////////////////////////////////////////////////////////////////////////////////////////////////////
        // PUBLIC PROCEDURES
        /////////////////////////////////////////////////////////////////////////////////////////////////////

        /// <summary>
        /// Returns the next <see cref="IToken"/> and seeks past it.
        /// </summary>
        /// <returns>The next <see cref="IToken"/>.</returns>
        protected override IToken GetNextTokenCore()
        {
            IToken token = null;
            int startOffset = this.TextBufferReader.Offset;

            while (!this.IsAtEnd)
            {
                // Get the next token
                token = this.Manager.GetNextToken();

                // Update whether there is non-whitespace since the last line start
                if (token.LexicalState == this.Language.DefaultLexicalState)
                {
                    switch (token.ID)
                    {
                        case SimpleTokenID.LineTerminator:
                        case SimpleTokenID.MultiLineComment:
                        case SimpleTokenID.SingleLineComment:
                        case SimpleTokenID.Whitespace:
                            // Consume non-significant token
                            break;
                        default:
                            // Return the significant token
                            return token;
                    }
                }
                else if (token.HasFlag(LexicalParseFlags.LanguageStart))
                {
                    // Return the significant token (which is in a different language)
                    return token;
                }

                // Advance the start offset
                startOffset = this.TextBufferReader.Offset;
            }

            // Return an end of document token
            if (this.Token != null)
                return this.Language.CreateDocumentEndToken(startOffset, this.Token.LexicalState);
            else
                return this.Language.CreateDocumentEndToken(startOffset, this.Language.DefaultLexicalState);
        }

    }
}
